package ig.util;
import java.util.*;
import java.math.*;

public class Matematica {
    
    /** Creates a new instance of Prueba */
    public Matematica() {
    }
    
  
    public static String evaluaExpresion(String ecuacion)throws java.lang.Exception{
        ecuacion = ecuacion.replaceAll("\\(", " \\( ");
        ecuacion = ecuacion.replaceAll("\\)", " \\) ");
        BigDecimal dres;
        StringTokenizer stz = new StringTokenizer(ecuacion," \t\n");
        String str = "";
        Stack s = new Stack();
        Stack op = new Stack();
        while(stz.hasMoreTokens()){
            str = stz.nextToken();
            if(str.compareTo(")") == 0){
                while ( "(".compareTo((String) s.peek() ) != 0){
                    str = (String)s.pop();
                    if("*;/;+;-;*;>=;<=;>;<;=;".indexOf(";" + str + ";")> 0){
                        dres = new BigDecimal((String)op.pop());
                        if(str.compareTo("/") == 0){
                            str = (dres.divide(new BigDecimal((String)op.pop()), 20,BigDecimal.ROUND_HALF_UP)).toString();
                        }else if(str.compareTo("+") == 0){
                            str = (dres.add(new BigDecimal((String)op.pop()))).toString();
                        }else if(str.compareTo("-") == 0){
                            str = (dres.subtract(new BigDecimal((String)op.pop()))).toString();
                        }else if(str.compareTo("*") == 0){
                            str = (dres.multiply(new BigDecimal((String)op.pop()))).toString();
                        }else if(str.compareTo(">=") == 0){
                            str = String.valueOf( (dres.compareTo(new BigDecimal((String)op.pop())) >= 0));
                        }else if(str.compareTo("<=") == 0){
                            str = String.valueOf( (dres.compareTo(new BigDecimal((String)op.pop())) <= 0));
                        }else if(str.compareTo(">") == 0){
                            str = String.valueOf( (dres.compareTo(new BigDecimal((String)op.pop())) > 0));
                        }else if(str.compareTo("<") == 0){
                            str = String.valueOf( (dres.compareTo(new BigDecimal((String)op.pop())) < 0));
                        }else{
                            str = String.valueOf( (dres.compareTo(new BigDecimal((String)op.pop())) == 0));
                        }
                        op.push(str);
                    }else if("if".compareToIgnoreCase(str) == 0) {
                        if(Boolean.valueOf((String)op.pop()).booleanValue()){
                            str = (String)op.pop();
                            op.pop();
                        }else{
                            op.pop();
                            str = (String)op.pop();
                        }
                        op.push(str);
                    }else{
                        op.push(str);
                    }
                }
                s.pop();
                s.push(op.pop());
            }else{
                s.push(str);
            }
        }
        if (s.size() + op.size() > 1 ){
            throw new Exception("formula mal formada");
        }
        return (String)s.pop();
    }
    
    public static boolean validaExpresion(String ecuacion)throws Exception{
        ecuacion = ecuacion.replaceAll("\\(", " \\( ");
        ecuacion = ecuacion.replaceAll("\\)", " \\) ");
        double dres;
        StringTokenizer stz = new StringTokenizer(ecuacion," \t\n");
        String str = "";
        Stack s = new Stack();
        Stack op = new Stack();
        try{
        while(stz.hasMoreTokens()){
            str = stz.nextToken();
            if(str.compareTo(")") == 0){
                while ( "(".compareTo((String) s.peek() ) != 0){
                    str = (String)s.pop();
                    if("*;/;+;-;*;>=;<=;>;<;=;".indexOf(";" + str + ";")> 0){
                        op.push(op.pop() + str + op.pop());
                    }else if("if".compareToIgnoreCase(str) == 0) {
                        str = "if" + op.pop() + "then" + op.pop()  + "else" + op.pop();
                        op.push(str);
                    }else{
                        op.push(str);
                    }
                }
                s.pop();
                s.push(op.pop());
            }else{
                s.push(str);
            }
        }
        }catch(Exception e){
            throw  new Exception("formula mal formada");
        }
        if (s.size() + op.size() > 1 ){
            throw new Exception("formula mal formada");
        }
        return true;
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String expresion = "(if (= campo1 campo2) (/ * campo3 campo4 (* campo5 campo6)) (campo7) )";
        try{
            if(validaExpresion(expresion)){
                System.out.println(evaluaExpresion("(if (= 0 0) (/ * 1 5 (* 12 2)) (+ - 4 6 8) )"));    
                System.out.println(evaluaExpresion("(/ * 10 5 (* 12 2))"));    
                System.out.println(evaluaExpresion("(+ * 4 6 8)"));    
                System.out.println(evaluaExpresion("( + (/ * 1 5 (* 12 2)) (+ - 4 6 8))"));    
                System.out.println(evaluaExpresion("(* 1 2)"));    
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        
    }

    /*
     * Cristhiam Reina
     * 5 de Agosto 2011
     * Funcion para ordenar arreglos, vectores y colecciones
     */
    public static double[] ordenarBurbuja(double  x[]){
            int i, j;
            double aux;

        for (i = 0; i < x.length; i++)
            {
                for (j = 0; j < x.length-1; j++)
                {
                    if (x[j] > x[j+1])
                    {
                        aux = x[j];
                        x[j] = x[j+1];
                        x[j+1] = aux;
                    }
                }
            }
            /*for (i = 0; i < x.length; i++){//AQUI SE RECORRE EL ARREGLO
                 System.out.println(x[i] + "  ");//AQUI SE IMPRIME EL ARREGLO YA ACOMODADO
            }*/

            return x;

    }


    public static double[] ordenarBurbuja(Vector<Double>  vec){

        double[] x = new double[vec.size()];

        int i = 0;

        for(double d: vec){
            x[i] = d;
            i++;
        }

        return ordenarBurbuja(x);
    }

    public static double[] ordenarBurbuja(Collection<Double> col){

        double[] x = new double[col.size()];

        int i = 0;

        for(double d: col){
            x[i] = d;
            i++;
        }

        return ordenarBurbuja(x);
    }


    public static double redondeardec(double numero, int decimales) {
            double resultado;
            BigDecimal res;

            res = new BigDecimal(numero).setScale(decimales, BigDecimal.ROUND_UP);
            resultado = res.doubleValue();
            return resultado;
	}
    
}
